﻿using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Shapes;
using System.Windows.Media;
using System.Windows.Media.Animation;
using Bling.DSL;
using Bling.Properties;
using Bling.Animation;
using Bling.WPF;
using Bling.Shapes;
using Bling.Slides;
using Bling.Util;
using Bling.Linq;

namespace Bling.Tutorial {
  public class Driver : SlideHolder {
    public Driver() {
      //this["ShaderReuse"] = () => new ShaderReuse();
      this["Title"] = () => new Title();
      this["Constraints"] = () => new Constraints();
      this["Chess"] = () => new Chess();
      this["Shaders"] = () => new Shaders();
      this["MetaBalls"] = () => new MetaBall();
      this["Tables"] = () => new Tables();
      this["Geom"] = () => {
        var ret = new CanvasBl();
        GeometryTest(ret);
        return ret;
      };
      this["Flip"] = () => new BookFlipDemo.FreeFlipCanvas();
      this["Tweens"] = () => new Tweens();
      this["Distort"] = () => new DistortTest();
      this["Bezier"] = () => new BezierTest();
      this["Bezier Scale"] = () => new BezierScaleTest();
      this["Pie"] = () => new PieTest();
      this["Ripple"] = () => new RipplesTest();
      this["Transitions"] = () => new TransitionsTest();
      Init();
    }
    [STAThread]
    public static void Main(string[] args) {
      var win = new Window() { Title = "Bling Tutorial", Content = new Driver() };
      new Application().Run(win);
      return;
    }
    public static void GeometryTest(CanvasBl canvas) {
      var pA = new ThumbBl(canvas) {
        Background = Brushes.Green, CanDrag = true, CenterPosition = new PointBl(10, 10), ZIndex = 1,
      };
      var pB = new ThumbBl(canvas) {
        Background = Brushes.Red, CanDrag = true, CenterPosition = new PointBl(400, 100), ZIndex = 1,
      };
      var pC = new ThumbBl(canvas) {
        Background = Brushes.Blue, CanDrag = true, CenterPosition = new PointBl(300, 300), ZIndex = 1,
      };
      var pD = new ThumbBl(canvas) {
        Background = Brushes.Purple, CanDrag = true, CenterPosition = new PointBl(100, 10), ZIndex = 1,
      };
      if (true) { // triangle base test.
        new LineBl(canvas) { Start = pA, End = pB };
        new LineBl(canvas) { Start = pA, End = pC };
        new LineBl(canvas) { Start = pB, End = pC };
        new LineBl(canvas) {
          Start = pA,
          End = pA.CenterPosition.TriangleBase(pB, pC),
          Stroke = { Brush = Brushes.Red, Thickness = 2, },
        };
      }
      if (true) { // circle test.
        new LineBl(canvas) {
          Start = pA,
          End = pB.CenterPosition.Spring(pA, 100),
          Stroke = { Brush = Brushes.Blue, Thickness = 2, },
        };
      }
      { // intersection test.
        new LineBl(canvas) { Start = pC, End = pD, };
        new LineBl(canvas) { Start = pA, End = pB, };
        var thumb = new ThumbBl(canvas) {
          Size = new Point(20, 20),
          CenterPosition = PointBl.Intersect(pA, pB, pC, pD),
        };
        thumb.Background = thumb.CenterPosition.Between(pC, pD).Condition(Brushes.Red, Brushes.Blue);

      }
      if (true) {
        var shape = new PathShapeBl(canvas) { Opacity = 0.2, Fill = Brushes.Black };
        var curve = new BezierSegmentBl();
        shape.Segments.Add(curve.CurrentValue);
        PointBl[] points = new PointBl[] {
          shape.Start, curve.Point1, curve.Point2, curve.Point3,
        };
        PointBl.Bezier(0, 0, points).Bind = pA;
        PointBl.Bezier(0.33, 1, points).Bind = pB;
        PointBl.Bezier(0.66, 2, points).Bind = pC;
        PointBl.Bezier(1, 3, points).Bind = pA;
      }
    }
  }

  public class ShaderReuse : Canvas {
    public ShaderReuse() {
      CanvasBl canvas = this;

      //var FFF = DoubleBl.Assign<double>(d=>canvas.Left.Now, d=>canvas.Top + d);


      var effect = EffectBl.Reuse<Ellipse>((input, uv, p) => {
        EllipseBl ellipse = p;
        var ratio = ellipse.CenterPosition / canvas.Size;
        var distance = (uv - ratio).Length;
        return input[uv] * distance;
      });
      var r = new Random();
      for (int i = 0; i < 10; i++) {
        var ellipse = new EllipseBl(canvas) {
          Fill = i.SelectColor(),
          Size = new PointBl(100, 100),
          CenterPosition = canvas.Size * ((PointBl)r),
        };
        ellipse.Effect = effect(ellipse);

      }
    }
  }


  public class Title : Canvas, CanStart {
    private readonly LabelBl title;
    public static readonly GetProperty<Title,double> AnimateProperty = "Animate".NewProperty<Title, double>();
    public DoubleBl Animate {
      get { return AnimateProperty[this]; }
      set { Animate.Bind = value; }
    }
    public Title() {
      CanvasBl MainCanvas = this.Bl();

      title = new LabelBl(this) {
        Font = { Size = 120, Weight = FontWeights.SemiBold, },
        CenterPosition = this.Bl().CenterSize,
        Content = "Bling Tutorial".Bl(),
        RenderTransform = { Rotate = 45.ToDegrees() * -1d + 90.ToDegrees() * Animate * Animate * Animate },
      };
      BrushBl noise = Bling.Tutorial.Properties.Resources.noise;
      title.Effect.Custom = (input, uv) => {
        var uv0 = new PointBl((uv.X + 13d * Animate), (uv.Y + 17d * Animate)) % 1d; 
        return ColorBl.FromScRGB(input[uv].ScA, noise[uv0].ScRGB);
      };

      return;
    }
    public void Start() {
      Animate.Animate.Forever().AutoReverse().To = 1;
    }
    public void Stop() {
      Animate.Stop(false);
    }
  }

}
